﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Domain.Model.Base
{
    /// <summary>
    /// Todas las entidades del dominio heredan de esta clase. 
    /// Sigue la recomendacion de  Tim Carley en su libro
    /// .Net Domain Driven Design with C#. Wiley Publishing, 2008
    /// </summary>
    public abstract class Entity:IdentifiedObject
    {
        #region Atributos Privados
        /// <summary>
        /// Atributo de identidad en el dominio
        /// </summary>
        private ObjectIdentity identity;

        #endregion

        #region Constructor

        protected Entity(ObjectIdentity identity)
        {
            if (identity == null)
            {
                throw new ArgumentNullException("Identity");
            }
            this.identity = identity;
        }
        protected Entity()
        {
            this.identity = null;
        }

        #endregion

        #region Propiedades

        /// <summary>
        /// Propiedad de solo lectura que permite obtener la identidad
        /// </summary>
        public ObjectIdentity Identity
        {
            get
            {
                return this.identity;
            }
        }

        public String Id
        {
            get { return this.Identity.Value.ToString(); }
        }

        #endregion

        #region Operadores de comparacion

        /// <summary>
        /// Comparacion entre dos entidades. Las entidades se consideran iguales
        /// si sus identidades son iguales.
        /// </summary>
        /// <param name="otherEntity"></param>
        /// <returns></returns>
        public override bool Equals(object otherEntity)
        {
            if (otherEntity == null || !(otherEntity is Entity))
            {
                return false;
            }
            return (((Entity)otherEntity).Identity.Equals(this.Identity));
        }

        /// <summary>
        /// Sobrecarga del operador ==
        /// </summary>
        /// <param name="entity1"></param>
        /// <param name="entity2"></param>
        /// <returns></returns>
        public static bool operator ==(Entity entity1, Entity entity2)
        {
            //Verdadero si las dos instancias son nulas
            if ((object)entity1 == null && (object)entity2 == null)
            {
                return true;
            }
            // Falso i una de las dos instancias es nula y la otra no
            if ((object)entity1 == null || (object)entity2 == null)
            {
                return false;
            }
            if (entity1.Identity != entity2.Identity)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Sobrecarga del operador !=
        /// </summary>
        /// <param name="entity1"></param>
        /// <param name="entity2"></param>
        /// <returns></returns>
        public static bool operator !=(Entity entity1, Entity entity2)
        {
            return (!(entity1 == entity2));
        }

        /// <summary>
        /// Necesaria para sobreescribir Equals
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Identity.GetHashCode();
        }

        #endregion
    }
}
